#include "./../../../include/online/Reactor/Socket.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <unistd.h>

// 默认构造函数：创建一个套接字
Socket::Socket()
{
    // 创建套接字：调用socket函数，返回一个文件描述符
    _fd = ::socket(AF_INET, SOCK_STREAM, 0);  // 创建一个IPv4协议的TCP套接字
    if (_fd < 0)
    {
        perror("socket");  // 如果创建套接字失败，打印错误信息
        return;
    }
}

// 用于accept成功后返回的connfd：客户端和服务端通信的文件描述符
Socket::Socket(int fd)
: _fd(fd)  // 使用初始化列表初始化_fd成员变量
{

}

// 析构函数：关闭套接字连接
Socket::~Socket()
{
    // 关闭套接字：调用close函数关闭文件描述符
    close(_fd);  // 关闭套接字，释放资源
}

// 获取套接字文件描述符
int Socket::getfd() const
{
    return _fd;  // 返回套接字的文件描述符
}

// 关闭写端：调用shutdown关闭套接字的写端
void Socket::shutDownWrite()
{
    int ret = shutdown(_fd, SHUT_WR);  // 使用shutdown系统调用关闭套接字的写端
    if (ret)
    {
        perror("shutdown");  // 如果shutdown失败，打印错误信息
        return;
    }
}


/*
    shutdown函数用于关闭网络套接字的一部分或全部连接。
    它通常用于 TCP 套接字，允许你控制如何关闭连接（例如，关闭发送、关闭接收，或同时关闭两者）。

    函数原型:
        #include <sys/socket.h>
        int shutdown(int sockfd, int how);
    参数:
        sockfd：要操作的套接字文件描述符。
        how：指定关闭的方式，可以是以下值之一：
            SHUT_RD：关闭读操作（接收数据）。
            SHUT_WR：关闭写操作（发送数据）。
            SHUT_RDWR：同时关闭读和写操作。
    返回值:
        成功时返回 0。      
        失败时返回 -1，并设置 errno 以指示错误。

    使用场景:
        优雅关闭连接：
            在TCP连接中，如果你想通知对方不再发送数据，但仍然可以接收数据，可以调用shutdown(sockfd, SHUT_WR)。
            这样可以确保对方收到 FIN 包，知道你已经完成了数据发送。
        关闭部分功能：
            如果你只想停止接收数据，但仍然可以发送数据，可以使用 SHUT_RD。
            如果你只想停止发送数据，但仍然可以接收数据，可以使用 SHUT_WR。
            完全关闭连接：
                使用 SHUT_RDWR 可以同时关闭读和写操作。

    注意事项:
        shutdown与close的区别：
            shutdown只关闭连接的一部分或全部功能，但不会释放套接字文件描述符。
            close会释放套接字文件描述符，并完全关闭连接。
        通常先调用 shutdown，再调用 close。
        SHUT_WR 的作用：
            调用 SHUT_WR 后，对方会收到 FIN 包，知道你已经完成了数据发送。
            对方仍然可以发送数据给你，直到对方也关闭连接。

        错误处理：
            如果 shutdown 失败，检查 errno 以确定错误原因。
*/